package com.xjj.sso.client.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSON;
import com.xjj.sso.client.SSOConstants;
import com.xjj.sso.client.filter.SSOClientFilter;
import com.xjj.sso.client.pojo.RequestParameter;
import com.xjj.sso.client.user.SSOReceipt;

public final class SSOUtils {

	private static String PREFIX_GT = "GT_";
	
	private static int SSO_COOKIE_MAXAGE=-1;
	private static String SSO_COOKIE_NAME="XJJTC";
	private static String SSO_COOKIE_PATH="/";
	
	private SSOUtils() {
	}

	public static void assertNotNull(final Object object, final String message) {
		if (object == null) {
			throw new IllegalArgumentException(message);
		}
	}

	@SuppressWarnings("rawtypes")
	public static void assertNotEmpty(final Collection c, final String message) {
		assertNotNull(c, message);
		if (c.isEmpty()) {
			throw new IllegalArgumentException(message);
		}
	}

	public static void assertTrue(final boolean cond, final String message) {
		if (!cond) {
			throw new IllegalArgumentException(message);
		}
	}

	public static boolean isEmpty(final String string) {
		return string == null || string.length() == 0;
	}

	public static boolean isNotEmpty(final String string) {
		return !isEmpty(string);
	}

	public static boolean isBlank(final String string) {
		return isEmpty(string) || string.trim().length() == 0;
	}

	public static boolean isNotBlank(final String string) {
		return !isBlank(string);
	}
	
	
	/**
	 * 判断url是否为受保护的资源(作废)
	 * @param uri
	 * @return
	 */
	public static boolean isNotFilter_bak(String uri,String contextPath) {
		if(isNotBlank(contextPath))
		{
			uri = uri.replace(contextPath, "");
			
		}
		String nof = SSOConfiguration.get("sso.client.nofilter");
		if(isBlank(nof))
		{
			return false;
		}
		
		
		String[] noArr = nof.split(",");
		String notemp = null;
		for (int i = 0; i < noArr.length; i++) {
			notemp = noArr[i];
			if(notemp.endsWith("*"))
			{
				notemp = notemp.substring(0,notemp.length()-1);
				if(uri.startsWith(notemp))
				{
					return true;
				}
			}else
			{
				if(uri.equals(notemp))
				{
					return true;
				}
			}
		}
		return false;
	}
	
	
	/**
	 * 判断url是否为受保护的资源
	 * @param uri
	 * @return
	 */
	public static boolean isNotFilter(String uri,String contextPath) {
		if(isNotBlank(contextPath))
		{
			uri = uri.replace(contextPath, "");
			
		}
		String nof = SSOConfiguration.get("sso.client.nofilter");
		if(isBlank(nof))
		{
			return false;
		}
		
		
		String[] noArr = nof.split(",");
		String notemp = null;
		boolean isNotFilter = false;
		for (int i = 0; i < noArr.length; i++) {
			notemp = noArr[i];
			
			if(isUrlMatching(uri,notemp))
			{
				isNotFilter = true;
				break;
			}
			
		}
		return isNotFilter;
	}
	
	/**
	 * url是否配
	 * @param srcUrl
	 * @param desUrl
	 * @return
	 */
	private static boolean isUrlMatching(String srcUrl,String desUrl){

		String des1 = desUrl.replace("*", "[.\\-\\w\\/]*");
		des1 = des1.replace("?", "\\w{1}");
		Pattern p = Pattern.compile(des1);
		Matcher m = p.matcher(srcUrl);
		return m.matches();
	}
	
	/**
	 * 验证ticket
	 * @param ticket
	 * @param service
	 * @return
	 */
	public static SSOReceipt validateTicket(String ticket, String service) {

		System.out.println("---------------------SSOUtils validateTicket begin---------------------");
		System.out.println("url="+SSOConstants.SSO_SERVER_VALIDATETICKET);
		System.out.println("service=="+service+"===");
		System.out.println("ticket=="+ticket+"===");
		System.out.println("---------------------SSOUtils validateTicket end---------------------");
		
		
		SSOReceipt receipt = null;

		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost httppost = new HttpPost(SSOConstants.SSO_SERVER_VALIDATETICKET);
		CloseableHttpResponse httpResponse = null;
		try {

			List<NameValuePair> formParams = new ArrayList<NameValuePair>();
			formParams.add(new BasicNameValuePair("service", service));
			formParams.add(new BasicNameValuePair("ticket", ticket));

			HttpEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");
			httppost.setEntity(entity);
			httpResponse = httpClient.execute(httppost);

			String content = EntityUtils.toString(httpResponse.getEntity(),
					"UTF-8");

			if (SSOUtils.isNotBlank(content)) {
				receipt = JSON.parseObject(content, SSOReceipt.class);
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(null !=httpClient)
				{
					httpClient.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return receipt;
	}
	
	
	/**
	 * 获得提交的参数
	 * @param session
	 * @param paramCode
	 * @param paramName
	 * @return
	 */
	public static String getParam(HttpSession session, String paramCode,String paramName) 
	{
		if(null == session)
		{
			return null;
		}
		
		Object requestPramObj = session.getAttribute("requestPram"+paramCode);
		if(null == requestPramObj)
		{
			return null;
		}
		RequestParameter param = (RequestParameter)requestPramObj;
		String paramValue= param.getParameter(paramName);
		return paramValue;
	}
	
	
	
	
	/**
	 * 截取项目code
	 * @param creentUri
	 * @param service
	 * @return
	 */
	public static String cutProjectCodeFormUrl(String contextPath,String requestURI) {
		
		String url = requestURI.replaceFirst(contextPath, "");
		if(url.startsWith("/"))
		{
			url = url.replaceFirst("/", "");
		}
		
		int firstFit = url.indexOf("/");
		String projectCode = url.substring(0, firstFit);
		
		return projectCode;
	}
	
	
	/**
	 * sso客户端的session注销，同时把缓存的ticket--session对应信息删除掉。
	 * @param session
	 */
	public static void sessionInvalidate(HttpSession session) {
		
		if(SSOClientFilter.SESSION_TICKET_CACHE.containsKey(session.getId()))
		{
			String ticket = SSOClientFilter.SESSION_TICKET_CACHE.get(session.getId());
			
			SSOClientFilter.TICKET_SESSION_CACHE.remove(ticket);
			SSOClientFilter.SESSION_TICKET_CACHE.remove(session.getId());
			session.invalidate();
			
		}
	}
	
	/**
	 * 无跳转单点登陆(由于cookie跨域问题，该方法还不能使用)
	 * @param request
	 * @param response
	 * @param loginName
	 * @param password
	 * @param isEncryption
	 * @return
	 */
	public static SSOReceipt ssoLogon(HttpServletRequest request,HttpServletResponse response,String loginName,String password,boolean isEncryption) {
		
		SSOReceipt receipt = null;
		String projectCode = SSOConstants.SSO_CLIENT_PROJECTCODE;
		StringBuilder preTicketSB = new StringBuilder(loginName);
		preTicketSB.append(projectCode);
		preTicketSB.append(System.currentTimeMillis());
		String cookieTicket = EncryptUtils.MD5Encode(preTicketSB.toString());
		String grantingTicket = PREFIX_GT+cookieTicket;
		writeCookie(response,grantingTicket);

		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost httppost = new HttpPost(SSOConstants.SSO_SERVER_URL+"/sso/logonNoRedirect");
		CloseableHttpResponse httpResponse = null;
		
		String service = getService(request);
		
		try {

			List<NameValuePair> formParams = new ArrayList<NameValuePair>();
			formParams.add(new BasicNameValuePair("loginName", loginName));
			formParams.add(new BasicNameValuePair("password", password));
			formParams.add(new BasicNameValuePair("projectCode", projectCode));
			formParams.add(new BasicNameValuePair("service", service));
			formParams.add(new BasicNameValuePair("grantingTicket", grantingTicket));
			formParams.add(new BasicNameValuePair("isEncryption", String.valueOf(isEncryption)));
			

			HttpEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");
			httppost.setEntity(entity);
			httpResponse = httpClient.execute(httppost);

			String content = EntityUtils.toString(httpResponse.getEntity(),
					"UTF-8");

			if (SSOUtils.isNotBlank(content)) {
				receipt = JSON.parseObject(content, SSOReceipt.class);
				
				//登陆成功
				request.getSession().setAttribute(SSOConstants.SSO_CLIENT_RECEIPT, receipt);
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpResponse.close();
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		return receipt;
	}
	
	
	/**
	 * 获得service
	 * @param request
	 * @param paramCode
	 * @param encode
	 * @return
	 * @throws UnsupportedEncodingException
	 */
    private static String getService(HttpServletRequest request){
        StringBuffer sb = new StringBuffer();
        sb.append(SSOConstants.HTTP_PRE);
        sb.append(SSOConstants.SSO_CLIENT_SERVERNAME);
        sb.append(request.getRequestURI());
        return sb.toString();
    }
    
    /**
	 * 写cookie值
	 * @param response
	 * @param ticket
	 */
	private static void writeCookie(HttpServletResponse response,String ticket)
	{
		Cookie cookie = new Cookie(SSO_COOKIE_NAME, ticket);		
		cookie.setMaxAge(SSO_COOKIE_MAXAGE);	
		cookie.setPath(SSO_COOKIE_PATH);
		response.addCookie(cookie);
	}
	
	public static void main_bak(String[] args) {
		String uri = "/icourse/login/login";
		String contextPath= "/icourse";
		System.out.println(isNotFilter(uri,contextPath));
		
	}
	public static void main(String[] args) {
//		String contextPath="/";
//		String requestURI="/icourse/index/index";
//		
//		
//		String url = requestURI.replaceFirst(contextPath, "");
//		if(url.startsWith("/"))
//		{
//			url = url.replaceFirst("/", "");
//		}
//		
//		int firstFit = url.indexOf("/");
//		String projectCode = url.substring(0, firstFit);
//		System.out.println(projectCode);
		
		//boolean a = isNotFilter("/aa/bb/cc",null);
		//System.out.println(a);
		
	}
}